package com.xwj.service.Impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xwj.Enums.StatusInfoEnum;
import com.xwj.dao.RaRepairInfoDao;
import com.xwj.dto.RepairInfoDto;
import com.xwj.entity.RaRepairInfo;
import com.xwj.service.Interface.RaRepairInfoService;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;

@Slf4j
@Service
@CacheConfig(cacheNames = "RaRepairInfoCache")
public class RaRepairInfoServiceImpl implements RaRepairInfoService {

    @Autowired
    private RaRepairInfoDao raRepairInfoDao;
    @Autowired
    private RaStatusInfoServiceImpl raStatusInfoService;

    private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();  //读写锁

    private Lock lock = readWriteLock.readLock();

    @Override
    @Cacheable(key = "#root.methodName+'_'+#pageIndex", unless = "#result.list.size() == 0")
    public PageInfo<RaRepairInfo> findAllInfo(int pageIndex, int pageSize) {
        PageHelper.startPage(pageIndex, pageSize);
        lock.lock();
        try {
            String label = StatusInfoEnum.RepirInfo.getName();
            List<RaRepairInfo> raRepairInfos = raRepairInfoDao.findAllInfo();
            raRepairInfos.forEach(raRepairInfo -> {
                Map<String, Object> map = new HashMap<>();
                map.put("label", label);
                map.put("type", raRepairInfo.getStatus());
                String status = raStatusInfoService.findOneStatus(map);
                raRepairInfo.setStatusStr(status);
            });
            PageInfo<RaRepairInfo> pageInfo = new PageInfo<>(raRepairInfos);
            return pageInfo;
        } catch (Exception e) {
            log.error("RaRepairInfoService异常:", e);
            e.printStackTrace();
            return new PageInfo<>(Collections.emptyList());
        } finally {
            lock.unlock();
        }
    }

    @Override
    @Cacheable(key = "#root.methodName+'_'+#pageIndex+'_'+#userId", unless = "#result.list.size() == 0")
    public PageInfo<RaRepairInfo> findRepairInfoByUserId(int pageIndex, int pageSize, String userId) {
        PageHelper.startPage(pageIndex, pageSize);
        lock.lock();
        try {
            String label = StatusInfoEnum.RepirInfo.getName();
            List<RaRepairInfo> raRepairInfos = raRepairInfoDao.findRepairInfoByUserId(userId);
            raRepairInfos.forEach(raRepairInfo -> {
                Map<String, Object> map = new HashMap<>();
                map.put("label", label);
                map.put("type", raRepairInfo.getStatus());
                String status = raStatusInfoService.findOneStatus(map);
                raRepairInfo.setStatusStr(status);
            });
            PageInfo<RaRepairInfo> pageInfo = new PageInfo<>(raRepairInfos);
            return pageInfo;
        } catch (Exception e) {
            log.error("RaRepairInfoService异常:", e);
            e.printStackTrace();
            return new PageInfo<>(Collections.emptyList());
        } finally {
            lock.unlock();
        }
    }

    @Override
    @Cacheable(key = "#root.methodName+'_'+#repairInfoDto.toString()+'_'+#pageIndex", unless = "#result.list.size() == 0")
    public PageInfo<RaRepairInfo> findByProperty(int pageIndex, int pageSize, RepairInfoDto repairInfoDto) {
        PageHelper.startPage(pageIndex, pageSize);
        lock.lock();
        try {
            String label = StatusInfoEnum.RepirInfo.getName();
            List<RaRepairInfo> raRepairInfos = raRepairInfoDao.findByProperty(repairInfoDto);
            raRepairInfos.forEach(raRepairInfo -> {
                Map<String, Object> map = new HashMap<>();
                map.put("label", label);
                map.put("type", raRepairInfo.getStatus());
                String status = raStatusInfoService.findOneStatus(map);
                raRepairInfo.setStatusStr(status);
            });
            PageInfo<RaRepairInfo> pageInfo = new PageInfo<>(raRepairInfos);
            return pageInfo;
        } catch (Exception e) {
            log.error("RaRepairInfoService异常:", e);
            e.printStackTrace();
            return new PageInfo<>(Collections.emptyList());
        } finally {
            lock.unlock();
        }
    }

    @Override
    @Cacheable(key = "#root.methodName+'_'+#repairInfoDto.toString()+'_'+#pageIndex", unless = "#result.list.size() == 0")
    public PageInfo<RaRepairInfo> frontFindByProperty(int pageIndex, int pageSize, RepairInfoDto repairInfoDto) {
        PageHelper.startPage(pageIndex, pageSize);
        lock.lock();
        try {
            String label = StatusInfoEnum.RepirInfo.getName();
            List<RaRepairInfo> raRepairInfos = raRepairInfoDao.frontFindByProperty(repairInfoDto);
            raRepairInfos.forEach(raRepairInfo -> {
                Map<String, Object> map = new HashMap<>();
                map.put("label", label);
                map.put("type", raRepairInfo.getStatus());
                String status = raStatusInfoService.findOneStatus(map);
                raRepairInfo.setStatusStr(status);
            });
            PageInfo<RaRepairInfo> pageInfo = new PageInfo<>(raRepairInfos);
            return pageInfo;
        } catch (Exception e) {
            log.error("RaRepairInfoService异常:", e);
            e.printStackTrace();
            return new PageInfo<>(Collections.emptyList());
        } finally {
            lock.unlock();
        }
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public int addOneInfo(RaRepairInfo raRepairInfo) {
        try {
            return raRepairInfoDao.addOneInfo(raRepairInfo);
        } catch (Exception e) {
            log.error("RaRepairInfoService异常:", e);
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    @Async("repairTaskAsyncPool")
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public Future<Boolean> addOneInfoSync(RaRepairInfo raRepairInfo) {
        Future<Boolean> future;
        try {
            raRepairInfoDao.addOneInfo(raRepairInfo);
            future = new AsyncResult<>(true);
        } catch (Exception e) {
            log.error("RaRepairInfoService异常:", e);
            e.printStackTrace();
            future = new AsyncResult<>(false);
        }
        return future;
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public int updateByProperty(String id, String userId, int status, String title, String reason, String phone, String address) {
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("id", id);
            map.put("userId", userId);
            map.put("status", status);
            map.put("title", title);
            map.put("reason", reason);
            map.put("phone", phone);
            map.put("address", address);
            map.put("updateTime", new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
            return raRepairInfoDao.updateByProperty(map);
        } catch (Exception e) {
            log.error("RaRepairInfoService异常:", e);
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    @Async("repairTaskAsyncPool")
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public Future<Boolean> updateByPropertySync(String id, String userId, int status, String title, String reason, String phone, String address) {
        Future<Boolean> future;
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("id", id);
            map.put("userId", userId);
            map.put("status", status);
            map.put("title", title);
            map.put("reason", reason);
            map.put("phone", phone);
            map.put("address", address);
            map.put("updateTime", new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
            raRepairInfoDao.updateByProperty(map);
            future = new AsyncResult<Boolean>(true);
        } catch (Exception e) {
            log.error("RaRepairInfoService异常:", e);
            e.printStackTrace();
            future = new AsyncResult<Boolean>(false);
        }
        return future;
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public int deleteByIds(List<String> ids) {
        try {
            if (ids.size() == 0)
                return 0;
            return raRepairInfoDao.deleteByIds(ids);
        } catch (Exception e) {
            log.error("RaRepairInfoService异常:", e);
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    @Cacheable(key = "#root.methodName+'_'+#id", unless = "#result == null")
    public Integer findRepairStatusById(String id) {
        try {
            return raRepairInfoDao.findRepairStatusById(id);
        } catch (Exception e) {
            log.error("RaRepairInfoService异常:", e);
            e.printStackTrace();
            return null;
        }

    }

    @Override
    @Async("repairTaskAsyncPool")
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public Future<Boolean> updateDelflag(List<String> ids) {
        Future<Boolean> future;
        try {
            raRepairInfoDao.updateDelflag(ids);
            future = new AsyncResult<Boolean>(true);
        } catch (Exception e) {
            log.error("RaRepairInfoService异常:", e);
            e.printStackTrace();
            future = new AsyncResult<Boolean>(false);
        }
        return future;
    }


    public List<String> parseListId(List<RaRepairInfo> raRepairInfos) {
        return raRepairInfos.stream().map(RaRepairInfo::getId).collect(Collectors.toList());
    }
}
